<template>
  <div 
    :class="[
      'bx-color-picker',
      'bx-glass',
      {
        'bx-color-picker--disabled': disabled,
        'bx-color-picker--focused': showPanel
      }
    ]"
    v-click-outside="handleClickOutside"
  >
    <div 
      class="bx-color-picker__trigger"
      @click="togglePanel"
    >
      <div 
        class="bx-color-picker__color-preview"
        :style="{ backgroundColor: displayColor }"
      ></div>
      <span class="bx-color-picker__value">{{ displayColor }}</span>
      <BxIcon name="chevron-down" class="bx-color-picker__arrow" />
      <BxIcon 
        v-if="clearable && displayColor"
        name="x-circle"
        class="bx-color-picker__clear"
        @click.stop="handleClear"
      />
    </div>

    <div 
      v-if="showPanel"
      class="bx-color-picker__panel bx-glass"
    >
      <div class="bx-color-picker__saturation-wrapper">
        <div 
          class="bx-color-picker__saturation"
          :style="{ backgroundColor: `hsl(${hue}, 100%, 50%)` }"
          @mousedown="handleSaturationMouseDown"
        >
          <div class="bx-color-picker__saturation-white"></div>
          <div class="bx-color-picker__saturation-black"></div>
          <div 
            class="bx-color-picker__saturation-pointer"
            :style="saturationPointerStyle"
          ></div>
        </div>
      </div>

      <div class="bx-color-picker__controls">
        <div class="bx-color-picker__hue-slider">
          <div 
            class="bx-color-picker__hue-track"
            @mousedown="handleHueMouseDown"
          >
            <div 
              class="bx-color-picker__hue-pointer"
              :style="huePointerStyle"
            ></div>
          </div>
        </div>

        <div class="bx-color-picker__alpha-slider">
          <div 
            class="bx-color-picker__alpha-track"
            :style="{ backgroundImage: alphaBgImage }"
            @mousedown="handleAlphaMouseDown"
          >
            <div 
              class="bx-color-picker__alpha-pointer"
              :style="alphaPointerStyle"
            ></div>
          </div>
        </div>
      </div>

      <div class="bx-color-picker__input-group">
        <BxInput 
          v-model="hexValue"
          label="HEX"
          @change="handleHexChange"
        />
        <BxInput 
          v-model="rgbaValue.r"
          label="R"
          type="number"
          @change="handleRgbaChange"
        />
        <BxInput 
          v-model="rgbaValue.g"
          label="G"
          type="number"
          @change="handleRgbaChange"
        />
        <BxInput 
          v-model="rgbaValue.b"
          label="B"
          type="number"
          @change="handleRgbaChange"
        />
        <BxInput 
          v-model="rgbaValue.a"
          label="A"
          type="number"
          step="0.01"
          min="0"
          max="1"
          @change="handleRgbaChange"
        />
      </div>

      <div 
        v-if="enablePreset"
        class="bx-color-picker__preset-colors"
      >
        <div 
          v-for="(color, index) in presetColors"
          :key="index"
          class="bx-color-picker__preset-item"
          :style="{ backgroundColor: color }"
          @click="selectPresetColor(color)"
        ></div>
      </div>
    </div>
  </div>
</template>

<script>
import { ref, computed, watch, onMounted, onUnmounted } from 'vue'
import BxInput from '../input/BxInput.vue'
import BxIcon from '../basic/BxIcon.vue'

export default {
  name: 'BxColorPicker',
  components: {
    BxInput,
    BxIcon
  },
  props: {
    modelValue: {
      type: String,
      default: '#000000ff'
    },
    placeholder: {
      type: String,
      default: '选择颜色'
    },
    disabled: {
      type: Boolean,
      default: false
    },
    readonly: {
      type: Boolean,
      default: false
    },
    clearable: {
      type: Boolean,
      default: false
    },
    size: {
      type: String,
      default: 'medium',
      validator: (value) => ['small', 'medium', 'large'].includes(value)
    },
    enableAlpha: {
      type: Boolean,
      default: true
    },
    enablePreset: {
      type: Boolean,
      default: true
    },
    presetColors: {
      type: Array,
      default: () => [
        '#000000ff', '#ffffff',
        '#ff0000ff', '#00ff00ff', '#0000ff',
        '#ffff00ff', '#00ffff', '#ff00ff'
      ]
    }
  },
  emits: ['update:modelValue', 'change', 'focus', 'blur'],
  directives: {
    clickOutside: {
      mounted(el, binding) {
        el.__clickOutsideHandler__ = (event) => {
          if (!(el === event.target || el.contains(event.target))) {
            binding.value(event)
          }
        }
        document.addEventListener('click', el.__clickOutsideHandler__)
      },
      unmounted(el) {
        document.removeEventListener('click', el.__clickOutsideHandler__)
      }
    }
  },
  setup(props, { emit }) {
    const showPanel = ref(false)
    const hue = ref(0) // 0-360
    const saturation = ref(0) // 0-1
    const lightness = ref(0) // 0-1
    const alpha = ref(1) // 0-1

    const hexValue = computed({
      get: () => rgbaToHex(rgbaValue.value),
      set: (val) => {
        const rgba = hexToRgba(val)
        if (rgba) {
          updateColorFromRgba(rgba)
        }
      }
    })

    const rgbaValue = computed({
      get: () => ({ r: Math.round(lightness.value * 255), g: Math.round(lightness.value * 255), b: Math.round(lightness.value * 255), a: alpha.value }), // Placeholder, will be updated by HSL conversion
      set: (val) => {
        updateColorFromRgba(val)
      }
    })

    const displayColor = computed(() => {
      return `hsla(${hue.value}, ${saturation.value * 100}%, ${lightness.value * 100}%, ${alpha.value})`
    })

    const saturationPointerStyle = computed(() => {
      return {
        left: `${saturation.value * 100}%`,
        top: `${(1 - lightness.value) * 100}%`
      }
    })

    const huePointerStyle = computed(() => {
      return {
        left: `${(hue.value / 360) * 100}%`
      }
    })

    const alphaPointerStyle = computed(() => {
      return {
        left: `${alpha.value * 100}%`
      }
    })

    const alphaBgImage = computed(() => {
      const color = `hsl(${hue.value}, ${saturation.value * 100}%, ${lightness.value * 100}%)`
      return `linear-gradient(to right, transparent, ${color})`
    })

    const togglePanel = () => {
      if (props.disabled) return
      showPanel.value = !showPanel.value
    }

    const handleClickOutside = () => {
      showPanel.value = false
    }

    const handleSaturationMouseDown = (event) => {
      if (props.disabled) return
      const el = event.currentTarget
      const rect = el.getBoundingClientRect()

      const update = (e) => {
        let x = (e.clientX - rect.left) / rect.width
        let y = (e.clientY - rect.top) / rect.height
        x = Math.max(0, Math.min(1, x))
        y = Math.max(0, Math.min(1, y))

        saturation.value = x
        lightness.value = 1 - y
        updateModelValue()
      }

      update(event)
      document.addEventListener('mousemove', update)
      document.addEventListener('mouseup', () => {
        document.removeEventListener('mousemove', update)
      })
    }

    const handleHueMouseDown = (event) => {
      if (props.disabled) return
      const el = event.currentTarget
      const rect = el.getBoundingClientRect()

      const update = (e) => {
        let x = (e.clientX - rect.left) / rect.width
        x = Math.max(0, Math.min(1, x))
        hue.value = x * 360
        updateModelValue()
      }

      update(event)
      document.addEventListener('mousemove', update)
      document.addEventListener('mouseup', () => {
        document.removeEventListener('mousemove', update)
      })
    }

    const handleAlphaMouseDown = (event) => {
      if (props.disabled || !props.enableAlpha) return
      const el = event.currentTarget
      const rect = el.getBoundingClientRect()

      const update = (e) => {
        let x = (e.clientX - rect.left) / rect.width
        x = Math.max(0, Math.min(1, x))
        alpha.value = x
        updateModelValue()
      }

      update(event)
      document.addEventListener('mousemove', update)
      document.addEventListener('mouseup', () => {
        document.removeEventListener('mousemove', update)
      })
    }

    const updateModelValue = () => {
      const hsla = `hsla(${hue.value}, ${saturation.value * 100}%, ${lightness.value * 100}%, ${alpha.value})`
      emit('update:modelValue', hsla)
      emit('change', hsla)
    }

    const selectPresetColor = (color) => {
      const rgba = hexToRgba(color)
      if (rgba) {
        updateColorFromRgba(rgba)
        updateModelValue()
      }
    }

    const handleHexChange = (newHex) => {
      const rgba = hexToRgba(newHex)
      if (rgba) {
        updateColorFromRgba(rgba)
        updateModelValue()
      }
    }

    const handleRgbaChange = () => {
      const rgba = { r: Number(rgbaValue.value.r), g: Number(rgbaValue.value.g), b: Number(rgbaValue.value.b), a: Number(rgbaValue.value.a) }
      updateColorFromRgba(rgba)
      updateModelValue()
    }

    const handleClear = () => {
      emit('update:modelValue', '')
      emit('change', '')
    }

    // Color conversion utilities
    const hexToRgba = (hex) => {
      if (!hex || typeof hex !== 'string') return null
      hex = hex.startsWith('#') ? hex.slice(1) : hex

      let r = 0, g = 0, b = 0, a = 1

      if (hex.length === 3) {
        r = parseInt(hex[0] + hex[0], 16)
        g = parseInt(hex[1] + hex[1], 16)
        b = parseInt(hex[2] + hex[2], 16)
      } else if (hex.length === 6) {
        r = parseInt(hex.substring(0, 2), 16)
        g = parseInt(hex.substring(2, 4), 16)
        b = parseInt(hex.substring(4, 6), 16)
      } else if (hex.length === 8) {
        r = parseInt(hex.substring(0, 2), 16)
        g = parseInt(hex.substring(2, 4), 16)
        b = parseInt(hex.substring(4, 6), 16)
        a = parseInt(hex.substring(6, 8), 16) / 255
      } else {
        return null
      }
      return { r, g, b, a }
    }

    const rgbaToHex = (rgba) => {
      if (!rgba) return ''
      const r = Math.round(rgba.r).toString(16).padStart(2, '0')
      const g = Math.round(rgba.g).toString(16).padStart(2, '0')
      const b = Math.round(rgba.b).toString(16).padStart(2, '0')
      const a = Math.round(rgba.a * 255).toString(16).padStart(2, '0')
      return `#${r}${g}${b}${props.enableAlpha ? a : ''}`
    }

    const rgbToHsl = (r, g, b) => {
      r /= 255, g /= 255, b /= 255
      const max = Math.max(r, g, b), min = Math.min(r, g, b)
      let h, s, l = (max + min) / 2

      if (max === min) {
        h = s = 0 // achromatic
      } else {
        const d = max - min
        s = l > 0.5 ? d / (2 - max - min) : d / (max + min)
        switch (max) {
          case r: h = (g - b) / d + (g < b ? 6 : 0); break;
          case g: h = (b - r) / d + 2; break;
          case b: h = (r - g) / d + 4; break;
        }
        h /= 6
      }
      return { h: h * 360, s, l }
    }

    const hslToRgb = (h, s, l) => {
      let r, g, b

      if (s === 0) {
        r = g = b = l // achromatic
      } else {
        const hue2rgb = (p, q, t) => {
          if (t < 0) t += 1
          if (t > 1) t -= 1
          if (t < 1 / 6) return p + (q - p) * 6 * t
          if (t < 1 / 2) return q
          if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6
          return p
        }

        const q = l < 0.5 ? l * (1 + s) : l + s - l * s
        const p = 2 * l - q
        r = hue2rgb(p, q, h + 1 / 3)
        g = hue2rgb(p, q, h)
        b = hue2rgb(p, q, h - 1 / 3)
      }

      return { r: Math.round(r * 255), g: Math.round(g * 255), b: Math.round(b * 255) }
    }

    const updateColorFromRgba = (rgba) => {
      const { r, g, b, a } = rgba
      const hsl = rgbToHsl(r, g, b)
      hue.value = hsl.h
      saturation.value = hsl.s
      lightness.value = hsl.l
      alpha.value = a
    }

    watch(() => props.modelValue, (newVal) => {
      if (newVal) {
        const rgba = hexToRgba(newVal) // Assuming modelValue is always hex or rgba string
        if (rgba) {
          updateColorFromRgba(rgba)
        }
      }
    }, { immediate: true })

    return {
      showPanel,
      hue,
      saturation,
      lightness,
      alpha,
      hexValue,
      rgbaValue,
      displayColor,
      saturationPointerStyle,
      huePointerStyle,
      alphaPointerStyle,
      alphaBgImage,
      togglePanel,
      handleClickOutside,
      handleSaturationMouseDown,
      handleHueMouseDown,
      handleAlphaMouseDown,
      selectPresetColor,
      handleHexChange,
      handleRgbaChange,
      handleClear
    }
  }
}
</script>

<style scoped>
.bx-color-picker {
  position: relative;
  display: inline-block;
  font-family: var(--bx-font-family);
}

.bx-color-picker__trigger {
  display: flex;
  align-items: center;
  padding: 8px 12px;
  border: 1px solid var(--bx-glass-border);
  border-radius: var(--bx-radius-medium);
  background: var(--bx-glass-bg);
  backdrop-filter: var(--bx-glass-blur);
  transition: all var(--bx-transition-medium);
  cursor: pointer;
}

.bx-color-picker__trigger:hover {
  border-color: var(--bx-glass-border-hover);
  background: var(--bx-glass-bg-hover);
}

.bx-color-picker--focused .bx-color-picker__trigger {
  border-color: rgba(0, 122, 255, 0.5);
  box-shadow: 0 0 0 2px rgba(0, 122, 255, 0.1);
}

.bx-color-picker__color-preview {
  width: 24px;
  height: 24px;
  border-radius: var(--bx-radius-small);
  border: 1px solid var(--bx-glass-border);
  margin-right: 8px;
}

.bx-color-picker__value {
  flex: 1;
  color: var(--bx-text-primary);
  font-size: 14px;
}

.bx-color-picker__arrow {
  font-size: 14px;
  color: var(--bx-text-secondary);
  transition: transform var(--bx-transition-medium);
}

.bx-color-picker--focused .bx-color-picker__arrow {
  transform: rotate(180deg);
}

.bx-color-picker__clear {
  font-size: 14px;
  color: var(--bx-text-tertiary);
  cursor: pointer;
  margin-left: 8px;
}

.bx-color-picker__clear:hover {
  color: var(--bx-text-primary);
}

.bx-color-picker__panel {
  position: absolute;
  top: calc(100% + 8px);
  left: 0;
  width: 280px;
  padding: 16px;
  border: 1px solid var(--bx-glass-border);
  border-radius: var(--bx-radius-medium);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
  z-index: 1000;
  animation: bx-fade-in-up 0.2s ease-out;
}

.bx-color-picker__saturation-wrapper {
  position: relative;
  width: 100%;
  padding-bottom: 75%; /* 4:3 aspect ratio */
  margin-bottom: 16px;
  overflow: hidden;
  border-radius: var(--bx-radius-small);
}

.bx-color-picker__saturation {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  cursor: crosshair;
}

.bx-color-picker__saturation-white {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: linear-gradient(to right, #fff, rgba(255, 255, 255, 0));
}

.bx-color-picker__saturation-black {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: linear-gradient(to top, #000, rgba(0, 0, 0, 0));
}

.bx-color-picker__saturation-pointer {
  position: absolute;
  width: 12px;
  height: 12px;
  border: 2px solid #fff;
  border-radius: 50%;
  box-shadow: 0 0 0 1.5px rgba(0, 0, 0, 0.16), inset 0 0 0 1px rgba(0, 0, 0, 0.16);
  transform: translate(-6px, -6px);
  cursor: grab;
}

.bx-color-picker__saturation-pointer:active {
  cursor: grabbing;
}

.bx-color-picker__controls {
  display: flex;
  gap: 16px;
  margin-bottom: 16px;
}

.bx-color-picker__hue-slider,
.bx-color-picker__alpha-slider {
  flex: 1;
  height: 10px;
  border-radius: 5px;
  position: relative;
  cursor: pointer;
}

.bx-color-picker__hue-slider {
  background: linear-gradient(to right, #f00 0%, #ff0 17%, #0f0 33%, #0ff 50%, #00f 67%, #f0f 83%, #f00 100%);
}

.bx-color-picker__alpha-slider {
  background-size: 10px 10px;
  background-repeat: repeat;
  background-image: linear-gradient(45deg, #ccc 25%, transparent 25%, transparent 75%, #ccc 75%, #ccc), linear-gradient(45deg, #ccc 25%, transparent 25%, transparent 75%, #ccc 75%, #ccc);
  background-position: 0 0, 5px 5px;
}

.bx-color-picker__hue-track,
.bx-color-picker__alpha-track {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
}

.bx-color-picker__hue-pointer,
.bx-color-picker__alpha-pointer {
  position: absolute;
  top: 50%;
  width: 12px;
  height: 12px;
  border: 2px solid #fff;
  border-radius: 50%;
  box-shadow: 0 0 0 1.5px rgba(0, 0, 0, 0.16), inset 0 0 0 1px rgba(0, 0, 0, 0.16);
  transform: translate(-6px, -6px);
  cursor: grab;
}

.bx-color-picker__hue-pointer:active,
.bx-color-picker__alpha-pointer:active {
  cursor: grabbing;
}

.bx-color-picker__input-group {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 8px;
  margin-bottom: 16px;
}

.bx-color-picker__preset-colors {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.bx-color-picker__preset-item {
  width: 24px;
  height: 24px;
  border-radius: var(--bx-radius-small);
  border: 1px solid var(--bx-glass-border);
  cursor: pointer;
  transition: transform var(--bx-transition-fast);
}

.bx-color-picker__preset-item:hover {
  transform: scale(1.1);
}

@keyframes bx-fade-in-up {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* 响应式设计 */
@media (max-width: 768px) {
  .bx-color-picker {
    width: 100%;
  }
  
  .bx-color-picker__panel {
    width: 100%;
    left: 0;
    right: 0;
  }
  
  .bx-color-picker__input-group {
    grid-template-columns: repeat(3, 1fr);
  }
}
</style>

